<template>
  <div class="hotel-detail">
    <div class="header" ref="targetElement">
      <div class="title">{{ hotelDetail.name }}</div>
      <div class="address">地址：{{ hotelDetail.address }}</div>
      <div class="cover">
        <img :src="hotelDetail.cover" alt="" />
      </div>
      <div class="bottom">
        <div class="booking">
          <el-button type="info" icon="el-icon-bell" plain @click="goBooking"
            >预定</el-button
          >
          <span>喜欢就来吧，先到先得哦~🥰</span>
        </div>
        <div class="option">
          <div class="write-remark" @click="dialogVisible = true">
            <i class="el-icon-edit"></i>点评
          </div>
          <div class="collect" @click="updateCollectStatus">
            <i
              :class="
                hotelDetail.status === 0
                  ? 'el-icon-star-off'
                  : 'el-icon-star-on'
              "
            ></i>
            {{ hotelDetail.status === 0 ? "收藏" : "已收藏" }}
          </div>
        </div>
      </div>
    </div>
    <!-- 预定 -->
    <div class="booking-container">
      <div class="content">
        <div class="form">
          <el-form
            :model="formData"
            ref="formData"
            :rules="rules"
            label-width="80px"
          >
            <el-form-item label="住房时间" prop="time">
              <el-date-picker
                v-model="formData.time"
                type="datetimerange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
              >
              </el-date-picker>
            </el-form-item>
            <el-form-item label="人数" prop="number">
              <el-input-number v-model="formData.number"></el-input-number>
            </el-form-item>
            <el-form-item label="身份证" style="width: 400px" prop="idCard">
              <el-input
                v-model="formData.idCard"
                placeholder="请输入身份证号"
              ></el-input>
            </el-form-item>
            <el-form-item label="手机号" style="width: 400px" prop="phone">
              <el-input
                v-model="formData.phone"
                placeholder="请输入手机号"
              ></el-input>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" :loading="loading" @click="booking"
                >立即预定</el-button
              >
            </el-form-item>
          </el-form>
        </div>
        <div class="table">
          <el-table
            :data="hotelSpecsList"
            stripe
            style="width: 100%"
            :header-cell-style="{ background: '#eef1f6', color: '#606266' }"
          >
            <el-table-column width="100" label="选择" align="center">
              <template slot-scope="scope">
                <el-radio
                  :label="scope.row.id"
                  v-model="formData.hotelSpecsId"
                  :disabled="scope.row.stock <= 0"
                  class="custom-radio"
                >
                </el-radio>
              </template>
            </el-table-column>
            <el-table-column
              prop="name"
              label="规格"
              align="center"
              :show-overflow-tooltip="true"
            >
            </el-table-column>
            <el-table-column
              prop="price"
              label="价格"
              width="150"
              align="center"
            >
            </el-table-column>
            <el-table-column
              prop="stock"
              label="库存"
              width="150"
              align="center"
            >
            </el-table-column>
          </el-table>
          <!-- 分页 -->
          <el-pagination
            v-show="hotelSpecsList.length > 0"
            layout="prev, pager, next"
            :total="total"
            :current-page="currentPage"
            :page-size="pageSize"
            @current-change="handleCurrentChange"
            :page-count="7"
            style="text-align: right; margin-top: 24px"
          >
          </el-pagination>
        </div>
      </div>
    </div>
    <!-- 介绍 -->
    <div class="introduce">
      <h3>酒店攻略</h3>
      <p>{{ hotelDetail.introduce }}</p>
    </div>
    <!-- 评论 -->
    <div class="remark user-common-bg">
      <RemarkView
        :remarkListLoading="remarkListLoading"
        :remarkList="remarkDataList"
        :total="remarkTotal"
        @getRemarkList="getRemarkList"
      ></RemarkView>
      <!-- 分页 -->
      <el-pagination
        v-show="remarkDataList.length > 0"
        background
        layout="prev, pager, next"
        :total="remarkTotal"
        :current-page="remarkCurrentPage"
        :page-size="remarkPageSize"
        @current-change="handleRemarkCurrentChange"
        :page-count="7"
        style="text-align: right; margin-top: 24px"
      >
      </el-pagination>
    </div>
    <!-- 写评论 -->
    <el-dialog
      title="写评论"
      :visible.sync="dialogVisible"
      width="56%"
      @close="html = ''"
      :close-on-click-modal="false"
    >
      <div class="editor-container">
        <Toolbar
          style="border-bottom: 1px solid #ccc"
          :editor="editor"
          :mode="mode"
        />
        <Editor
          style="height: 210px; overflow-y: hidden"
          v-model="html"
          :defaultConfig="editorConfig"
          :mode="mode"
          @onCreated="onCreated"
        />
      </div>
      <span slot="footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addRemark" :loading="insertLoading"
          >确 定</el-button
        >
      </span>
    </el-dialog>
    <!-- 侧边功能区 -->
    <div class="flexd" v-show="isShow">
      <i class="el-icon-bell" @click="goBooking"></i>
      <i class="el-icon-edit" @click="dialogVisible = true"></i>
      <i
        @click="updateCollectStatus"
        :class="
          hotelDetail.status === 0 ? 'el-icon-star-off' : 'el-icon-star-on'
        "
        :style="hotelDetail.status === 0 ? '' : 'color: #ff9900'"
      ></i>
      <i class="el-icon-arrow-up" @click="goTop"></i>
    </div>
  </div>
</template>

<script>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import RemarkView from "@/components/RemarkView.vue";
import { addHotelBooking } from "@/api/user/booking";
import { getHotelDetail, getHotelSpecsList } from "@/api/user/hotel";
import userModule from "@/utils/userInfo";
import { addRemark, getRemarkList } from "@/api/user/remark";
import { uploadFile } from "@/api/common";
import { Notification } from "element-ui";
import { updateHotelCollectStatus } from "@/api/user/collect";

export default {
  name: "HotelDetail",
  props: ["id"],
  components: {
    RemarkView,
    Editor,
    Toolbar,
  },
  data() {
    return {
      hotelDetail: {},
      formData: {
        userId: "",
        hotelId: "",
        time: "",
        number: 1,
        idCard: "",
        phone: "",
        hotelSpecsId: null,
        bookingStartTime: "",
        bookingEndTime: "",
      },
      rules: {
        time: [
          { required: true, message: "请选择住房时间", trigger: "blur" },
          {
            validator: (rule, value, callback) => {
              const now = new Date().getTime();
              const oneDayInMillisecods = 24 * 60 * 60 * 1000;
              const previousDayTimestamp = now - oneDayInMillisecods;
              const lastDate = new Date(previousDayTimestamp);

              const selectedFirstDate = new Date(value[0]);
              const selectSecondDate = new Date(value[1]);

              if (selectedFirstDate < lastDate || selectSecondDate < lastDate) {
                callback(new Error("不能为今天以前的时间"));
              } else {
                callback();
              }
            },
            trigger: "blur",
          },
        ],
        number: [{ required: true, message: "请选择人数", trigger: "blur" }],
        idCard: [
          { required: true, message: "请输入身份证号", trigger: "blur" },
          {
            pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
            message: "请输入正确的身份证号",
            trigger: "blur",
          },
        ],
        phone: [
          { required: true, message: "请输入手机号", trigger: "blur" },
          {
            pattern: /^1[3456789]\d{9}$/,
            message: "请输入正确的手机号",
            trigger: "blur",
          },
        ],
      },
      loading: false,
      hotelSpecsList: [],
      page: 1,
      pageSize: 5,
      currentPage: 1,
      total: 0,
      remarkDataList: [],
      remarkPage: 1,
      remarkPageSize: 10,
      remarkCurrentPage: 1,
      remarkTotal: 0,
      remarkListLoading: false,
      dialogVisible: false,
      insertLoading: false,
      collectLoading: false,
      // 富文本框配置
      editor: null,
      html: "",
      editorConfig: {
        placeholder: "请输入内容...",
        MENU_CONF: {},
      },
      mode: "default", // or 'simple'
      // 滚动条设置
      scrollTop: 0,
      isShow: false,
    };
  },
  created() {
    this.getHotelDetail();
    this.getHotelSpecsList();
    this.getRemarkList();
    // 图片配置设置
    this.configImage();
    // 视频配置设置
    this.configVideo();
  },
  mounted() {
    window.addEventListener("scroll", this.handleScroll);
    this.handleScroll(); // 组件挂载时立即执行一次，确保初始位置正确
  },
  beforeDestroy() {
    window.removeEventListener("scroll", this.handleScroll);

    const editor = this.editor;
    if (editor == null) return;
    editor.destroy(); // 组件销毁时，及时销毁编辑器
  },
  methods: {
    // 去预约
    goBooking() {
      const height = this.$refs.targetElement.offsetHeight;
      window.scrollTo({
        top: height,
        behavior: "smooth",
      });
    },
    // 回到顶部
    goTop() {
      window.scrollTo({
        top: 0,
        behavior: "smooth",
      });
    },
    // 获取酒店详情
    async getHotelDetail() {
      const res = await getHotelDetail({ id: this.id });
      this.hotelDetail = res.data;
    },
    // 获取酒店规格列表
    async getHotelSpecsList() {
      const res = await getHotelSpecsList({
        page: this.page,
        pageSize: this.pageSize,
        hotelId: this.id,
      });
      this.hotelSpecsList = res.data.records;
      this.total = res.data.total;
    },
    // 立即预定
    booking() {
      this.$refs.formData.validate(async (v) => {
        if (v) {
          if (this.formData.hotelSpecsId === null) {
            this.$message.error("请选择房型");
            return;
          }
          this.formData.bookingStartTime = this.formData.time[0];
          this.formData.bookingEndTime = this.formData.time[1];
          this.formData.hotelId = this.id;
          this.formData.userId = userModule.getUser().id;
          try {
            this.loading = true;
            const res = await addHotelBooking(this.formData);

            this.$refs.formData.resetFields();
            this.formData.hotelSpecsId = null;
            this.formData.bookingStartTime = null;
            this.formData.bookingEndTime = null;

            this.getHotelSpecsList();
          } catch {
            this.$message.error("预定失败");
          } finally {
            this.loading = false;
          }
        }
      });
    },
    // 添加评论
    async addRemark() {
      const content = this.html;
      if (content === "") {
        this.$message.warning("请输入评论内容");
        return;
      }
      try {
        this.insertLoading = true;
        const res = await addRemark({
          userId: userModule.getUser().id,
          type: "hotel",
          typeId: this.id,
          content,
        });
        this.dialogVisible = false;
        this.getRemarkList();
      } finally {
        this.insertLoading = false;
      }
    },
    // 获取评论列表
    async getRemarkList() {
      try {
        this.remarkListLoading = true;
        const res = await getRemarkList({
          page: this.remarkPage,
          pageSize: this.remarkPageSize,
          type: "hotel",
          typeId: this.id,
        });
        this.remarkDataList = res.data.records;
        this.remarkTotal = res.data.total;
      } catch {
        this.$message.error("获取评论列表失败");
      } finally {
        this.remarkListLoading = false;
      }
    },
    // 收藏
    async updateCollectStatus() {
      try {
        this.collectLoading = true;
        const res = await updateHotelCollectStatus({
          id: this.id,
          status: this.hotelDetail.status === 0 ? 1 : 0,
        });
        this.getHotelDetail();
        this.$notify.success({
          message: "操作成功",
        });
      } catch {
        this.$notify.error({
          message: "操作失败",
        });
      } finally {
        this.collectLoading = false;
      }
    },
    // 富文本框配置
    onCreated(editor) {
      this.editor = Object.seal(editor); // 一定要用 Object.seal() ，否则会报错
    },
    // 富文本框自定义图片上传
    configImage() {
      this.editorConfig.MENU_CONF["uploadImage"] = {
        // 自动定义上传图片
        async customUpload(file, insertFn) {
          // 判断格式是否正确
          const isJPG = file.type === "image/jpeg" || file.type === "image/png";
          const isLt10M = file.size / 1024 / 1024 < 10;
          if (!isJPG) {
            this.$message.error("上传图片只能是 jpg/jpeg/png 格式!");
            return false;
          }
          if (!isLt10M) {
            this.$message.error("上传图片大小不能超过 10MB!");
            return false;
          }

          const notify = Notification({
            title: "提示",
            message: "正在上传图片",
            showClose: false,
            iconClass: "el-icon-loading",
            duration: 0,
          });
          try {
            // 上传到服务器
            let formData = new FormData();
            // 拿到存在file中的文件存放到formData中s
            formData.append("file", file);
            const res = await uploadFile(formData);
            insertFn(res.data);
            notify.close();
            Notification.success({
              title: "上传成功",
              duration: 2000,
            });
          } catch {
            notify.close();
            Notification.error({
              title: "错误",
              message: "上传失败",
              duration: 2000,
            });
          }
        },
      };
    },
    // 富文本框自定义视频上传
    configVideo() {
      this.editorConfig.MENU_CONF["uploadVideo"] = {
        // 自动定义上传视频
        async customUpload(file, insertFn) {
          // 判断格式是否正确
          const isJPG = file.type === "video/mp4";
          const isLt20M = file.size / 1024 / 1024 < 20;
          if (!isJPG) {
            this.$message.error("上传视频只能是 mp4 格式!");
            return false;
          }
          if (!isLt20M) {
            this.$message.error("上传视频大小不能超过 20MB!");
            return false;
          }

          const notify = Notification({
            title: "提示",
            message: "正在上传视频",
            showClose: false,
            iconClass: "el-icon-loading",
            duration: 0,
          });
          try {
            // 上传到服务器
            let formData = new FormData();
            // 拿到存在file中的文件存放到formData中s
            formData.append("file", file);
            const res = await uploadFile(formData);
            insertFn(res.data);
            notify.close();
            Notification.success({
              title: "上传成功",
              duration: 2000,
            });
          } catch {
            notify.close();
            Notification.error({
              title: "错误",
              message: "上传失败",
              duration: 2000,
            });
          }
        },
      };
    },
    // 分页
    handleCurrentChange(page) {
      this.page = page;
      this.currentPage = page;
      this.getHotelSpecsList();
    },
    handleRemarkCurrentChange(page) {
      this.page = page;
      this.currentPage = page;
      this.getRemarkList();
    },
    // 获取滚动条高度
    handleScroll() {
      this.scrollTop = window.scrollY;
      // 获取指定容器的高度
      const height = this.$refs.targetElement.offsetHeight;
      this.isShow = this.scrollTop > height - 20;
    },
  },
};
</script>

<style lang="less" scoped>
.hotel-detail {
  .header {
    padding: 10px 100px;
    min-height: 400px;
    text-align: left;
    box-shadow: 0 2px 6px #cfcfcf;
    .title {
      font-size: 24px;
      font-weight: bold;
    }
    .address {
      margin: 10px 0;
      font-size: 14px;
      color: #999;
    }
    .cover {
      width: 80%;
      height: 400px;
      border-radius: 6px;
      img {
        width: 100%;
        height: 100%;
        border-radius: inherit;
      }
    }
    .bottom {
      display: flex;
      justify-content: space-between;
      height: 50px;
      .booking {
        display: flex;
        align-items: flex-end;
        height: 100%;
        line-height: 50px;
        span {
          height: 28px;
          line-height: 28px;
          margin-left: 10px;
          font-size: 13px;
          color: #999;
        }
      }
      .option {
        width: 240px;
        height: 100%;
        line-height: 50px;
        display: flex;
        .collect,
        .write-remark {
          position: relative;
          padding-top: 10px;
          height: 100%;
          cursor: pointer;
          font-size: 18px;
          &::after {
            content: "";
            position: absolute;
            bottom: 0;
            left: 50%;
            width: 0;
            height: 2px;
            background-color: #333;
            transition: all 0.3s ease-in-out;
            transform: translate(-x(-50%));
          }
          &:hover::after {
            width: 100%;
            left: 0;
          }
          i {
            margin-right: 4px;
            font-size: 24px;
            color: rgb(255, 168, 0);
          }
        }
        .collect {
          margin-left: 40px;
          i {
            margin-right: 0;
          }
        }
      }
    }
  }
  .booking-container {
    padding: 10px 100px;
    min-height: 360px;
    text-align: left;
    .content {
      display: flex;
      .form {
        width: 40%;
      }
      .table {
        flex: 1;
        border-left: 1px solid #ddd;
        border-right: 1px solid #ddd;
        border-bottom: 1px solid #ddd;
      }
    }
  }
  .introduce {
    display: flex;
    justify-content: space-between;
    margin: 10px 100px;
    padding-top: 16px;
    min-height: 120px;
    border-top: 1px solid #999;
    text-align: left;
    color: #666;
    p {
      width: 88%;
      line-height: 24px;
    }
  }
  .remark {
    margin: 10px auto;
    min-height: 300px;
    border-top: 1px dashed #eee;
  }
  .flexd {
    position: fixed;
    right: 10px;
    top: 28%;
    display: flex;
    flex-direction: column;
    width: 60px;
    height: 240px;
    box-shadow: 0 0 6px #ccc;
    background-color: #fff;
    i {
      font-size: 18px;
      width: 60px;
      height: 60px;
      line-height: 60px;
      cursor: pointer;
      &:hover {
        color: rgb(255, 168, 0);
      }
      &:nth-of-type(1),
      &:nth-of-type(2),
      &:nth-of-type(3) {
        border-bottom: 1px solid #ddd;
      }
      &:nth-of-type(3) {
        font-size: 20px;
      }
    }
  }
  .editor-container {
    text-align: left;
    border: 1px solid;
  }
  /* 自定义样式隐藏标签文本 */
  /deep/.el-radio__label {
    display: none;
  }
}
</style>